/*
 * Copyright 2010, 2011 Matt Oliveri
 *
 * This file is part of JConfigGen
 *
 * JConfigGen is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JConfigGen is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with JConfigGen.  If not, see <http://www.gnu.org/licenses/>.
 */

package atma.jconfiggen;

import java.io.PrintStream;

/** Refer to an expression result multiple times.
 * <p>
 * This expression type acts as a sort of proxy for referring to the result of its subexpression multiple times without having to assign an id.
 * The evaluation and result of a {@code Proxy} are the same as those of the {@code Proxy}'s subexpression.
 * </p>
 * <p>
 * You refer to the result of a {@code Proxy} with a {@link PxRef} expression.
 * The {@code Proxy} (including its subexpression) is only evaluated once regardless of how many times its result is used.
 * </p>
 * <p>
 * There is a restriction on where a {@link PxRef} can be, relative to the {@code Proxy} it refers to.
 * The restriction is described in the description of {@link PxRef}.
 * </p>
 */
public final class Proxy extends Expr
{
	private final Expr exp;
	private boolean usingId;

	/** Construct a {@code Proxy}.
	 * @param e The subexpression.
	 */
	public Proxy(Expr e) {exp = e;}

	void printType(PrintStream out) throws InvalidConfigException {exp.printType(out);}
	boolean hasStats() {return true;}
	void discard() {}
	void statize() {}

	// This implementation of useId is safe to call multiple times, which is good, since each PxRef to this Proxy might call it.
	boolean useId(String i)
	{
		if (usingId) return false;
		if (exp.useId(i)) {usingId = true;return true;}
		return false;
	}

	void printStats(PrintStream out,int tabs) throws InvalidConfigException
	{
		if (!usingId) exp.statize();
		exp.printStats(out,tabs);
	}

	void printExpr(PrintStream out) {exp.printExpr(out);}
}
